#include "User_Uart.h"
#include "User_Flash.h"
#include "stdio.h"
#include "User_sensor_data_cacl.h"
#include "main.h"
#include "string.h"
#include "TCS3410_Driver.h"

char tri_args_buf[ARGS_BUF_SIZE];
char cal_args_buf[ARGS_BUF_SIZE];
char parameter_buf[ARGS_BUF_SIZE];
uint8_t debug_receive_buff[DEBUG_BUFF_SIZE];
uint8_t rs232_receive_buff[RS232_BUFF_SIZE];
uint8_t debug_task_buff[DEBUG_BUFF_SIZE];


extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart1_tx;
extern DMA_HandleTypeDef hdma_usart2_rx;
extern DMA_HandleTypeDef hdma_usart2_tx;


extern char *p_cal_data_agrs;
extern char *p_tri_data_agrs;
extern char *p_paratemer;
char uart1_ready_flag = 0;
char uart2_ready_flag = 0;

enum {
    CMD_ID_HELP = 0,
    CMD_ID_DETECTION,
    CMD_ID_TRIGGER,
	CMD_ID_CAL,
	CMD_ID_SHOW_CAL_DATA,
	CMD_ID_SHOW_TRIGGER_DATA,
	CMD_ID_TEST_DETECTION,
	CMD_ID_FILL_LIGHT_ENABLE,
	CMD_ID_FILL_LIGHT_DISABLE,
	CMD_ID_SET_SAMPLE_BREATHING_PARAMETER,
	CMD_ID_GET_SAMPLE_BREATHING_PARAMETER
};



command_entry_t command_table[] = {
    { "help",  NULL,CMD_ID_HELP,"show all command list"},
	{"detection_led",NULL,CMD_ID_DETECTION,"start detection_led retrun R,G,B,Clear return fomat is json"},
	{"trigger_led",NULL,CMD_ID_TRIGGER,"setting trigger led data example:trigger_led Trigger_1 R:123 G:45 B:67 C:89"},
	{"calibration_led",NULL,CMD_ID_CAL,"setting ALS data example:calibration_led calibration_led red min:30 max:330"},
	{"show_als_cal_data",NULL,CMD_ID_SHOW_CAL_DATA,"show als calibration data"},
	{"show_als_tri_data",NULL,CMD_ID_SHOW_TRIGGER_DATA,"show als trigger data"},
	{"enable_fill_light",NULL,CMD_ID_FILL_LIGHT_ENABLE,"enable fill LED default status:enable"},
	{"disable_fill_light",NULL,CMD_ID_FILL_LIGHT_DISABLE,"disable fill LED default status:enable"},
	{"test_detection_led",NULL,CMD_ID_TEST_DETECTION,"test detection_led example:test_detection_led R:125 G:100 B:55 C:100"},
	{"set_sameple_breathing_parameter",NULL,CMD_ID_SET_SAMPLE_BREATHING_PARAMETER,"set sample conut and breathing parameter example:set_sameple_breathing_parameter sample:5 breathing_thd:300 breathing_count:2"},
	{"get_sameple_breathing_parameter",NULL,CMD_ID_GET_SAMPLE_BREATHING_PARAMETER,"return parameter list"},
};

const int command_table_size = sizeof(command_table) / sizeof(command_table[0]);


static void handle_command_by_id(uint8_t cmd_id, char *args)
{
    switch (cmd_id)
    {
        case CMD_ID_HELP:
            help_cmd();
            break;
        case CMD_ID_DETECTION:
            g_system.detection_led_rdy = 1;
            break;
        case CMD_ID_TRIGGER:
			g_system.trigger_flag = 1;
			copy_args(tri_args_buf,args);
			p_tri_data_agrs = tri_args_buf;
            break;
        case CMD_ID_CAL:
			g_system.cal_flag = 1;
			copy_args(cal_args_buf,args);
			p_cal_data_agrs = cal_args_buf;
            break;
		case CMD_ID_SHOW_TRIGGER_DATA:
			PrintColorData(0);
			break;
		case CMD_ID_SHOW_CAL_DATA:
			PrintHueThresholds(0);
			break;
		case CMD_ID_TEST_DETECTION:
			g_system.detection_led_rdy = 1;
			g_system.test_sensor = 1;
			break;
		case CMD_ID_FILL_LIGHT_ENABLE:
			g_system.enable_fill_led = 1;
			break;
		case CMD_ID_FILL_LIGHT_DISABLE:
			g_system.disable_fill_led = 1;
			break;
		case CMD_ID_SET_SAMPLE_BREATHING_PARAMETER:
			g_system.parameter_flag = 1;
			copy_args(parameter_buf,args);
			p_paratemer = parameter_buf;
			break;
		case CMD_ID_GET_SAMPLE_BREATHING_PARAMETER:
			print_parameter_list();
			break;
        default:
            HAL_UART_Transmit(&huart1, (uint8_t *)"Unknown ID\r\n", 13, HAL_MAX_DELAY);
            break;
    }
}




void Uart_Task(void)
{
	if(uart1_ready_flag || uart2_ready_flag)
    {
        uart1_ready_flag = 0;
		uart2_ready_flag = 0;
        parse_commands(debug_task_buff, strlen((char*)debug_task_buff), handle_cmd);
        memset(debug_task_buff, 0, sizeof(debug_task_buff));
		
    }
	
}

static void copy_args(char *args_buf,const char *args)
{
	strncpy(args_buf, args, ARGS_BUF_SIZE - 1);
    args_buf[ARGS_BUF_SIZE - 1] = '\0'; 
}

static void help_cmd()
{
    printf("\r\n--------------commands List--------------\r\n");
    for (int i = 0; i < command_table_size; i++) {
        const char *name = command_table[i].name;
		const char *describe = command_table[i].help;
		printf("- %-32s%s\r\n",(uint8_t *)name,(uint8_t *)describe);
    }
	printf("------------------------------------------");
}

static void print_parameter_list()
{
	printf("\r\n--------------parameter List--------------\r\n");
	printf("sample: %u\r\n", g_system.sampling_count);
	printf("breathing_thd: %u\r\n", g_system.breathing_thd);
	printf("breathing_count: %u\r\n", g_system.breathing_count);
	printf("------------------------------------------");
}


static void parse_commands(uint8_t *buff, uint16_t len, void (*handle_cmd)(uint8_t *cmd, uint16_t cmd_len)) 
{
    uint16_t i = 0, start = 0;

    while (i < len - 1) 
	{
        if (buff[i] == '\r' && buff[i + 1] == '\n') 
		{
            uint16_t cmd_len = i - start;
            if (cmd_len > 0) 
				handle_cmd(&buff[start], cmd_len);  
            i += 2;
            start = i;
        } 
		else i++;
    }
}

static void handle_cmd(uint8_t *cmd, uint16_t cmd_len) 
{
    char temp[128] = {0};
    memcpy(temp, cmd, cmd_len);
    temp[cmd_len] = '\0';

    char *cmd_name = strtok(temp, " ");
    char *args = strtok(NULL, "");

    for (int i = 0; i < command_table_size; i++)
	{
        if (strcmp(cmd_name, command_table[i].name) == 0) 
		{
            handle_command_by_id(command_table[i].id, args);
            return;
        }
    }
	printf("Unknown command\r\n");
}


int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}
 
int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart2, &ch, 1, 0xffff);
  return ch;
}

static void USAR_UART2_IDLECallback(UART_HandleTypeDef *huart)
{
    HAL_UART_DMAStop(&huart2);                                                     
    
    uint8_t data_length  = RS232_BUFF_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);  
	if(data_length)
	{
		memcpy(debug_task_buff,rs232_receive_buff,data_length);
		uart2_ready_flag = 1;
		
	}                    

    memset(rs232_receive_buff,0,data_length);                                           
    data_length = 0;
    HAL_UART_Receive_DMA(&huart2, (uint8_t*)rs232_receive_buff, RS232_BUFF_SIZE);                
}


static void USER_UART2_IRQHandler(UART_HandleTypeDef *huart)
{
	if(USART2 == huart2.Instance)                                   
    {
        if(RESET != __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE))   
        {
            __HAL_UART_CLEAR_IDLEFLAG(&huart2);		
            USAR_UART2_IDLECallback(huart);                          
        }
    }
}


static void USAR_UART1_IDLECallback(UART_HandleTypeDef *huart)
{
    HAL_UART_DMAStop(&huart1);                                                     
    
    uint8_t data_length  = DEBUG_BUFF_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);                    
	
	if(data_length)
	{
		memcpy(debug_task_buff,debug_receive_buff,data_length);
		uart1_ready_flag = 1;
		
	}

    memset(debug_receive_buff,0,data_length);                                           
    data_length = 0;
    HAL_UART_Receive_DMA(&huart1, (uint8_t*)debug_receive_buff, DEBUG_BUFF_SIZE);                
}


static void USER_UART1_IRQHandler(UART_HandleTypeDef *huart)
{
    if(USART1 == huart1.Instance)                                   
    {
        if(RESET != __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))   
        {
            __HAL_UART_CLEAR_IDLEFLAG(&huart1);                     
            USAR_UART1_IDLECallback(huart);                          
        }
    }
}

/**
  * @brief This function handles USART1 global interrupt.
  */
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
	USER_UART1_IRQHandler(&huart1); 
  /* USER CODE END USART1_IRQn 1 */
}

/**
  * @brief This function handles USART2 global interrupt.
  */
void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */

  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */
	USER_UART2_IRQHandler(&huart2); 
  /* USER CODE END USART2_IRQn 1 */
}

